home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
TPUG - Toronto PET Users Group
/
TPUG Users Group CD
/
TPUG Users Group CD.iso
/
AMIGA
/
AMICUS
/
AMICUS19.ADF
/
Solve
/
Solve.asm
< prev
next >
Wrap
Assembly Source File
|
1989-01-27
|
13KB
|
271 lines
*
* Program to solve a linear system using FFP numbers
* Copyright ⌐ 1986 by Allen Barnett
* Troy, NY
*
*
* Declare externals so the linker can find them
*
XREF _AbsExecBase ;base address for the exec library
;jump table
XREF _LVOOpenLibrary ;open a library (exec)
XREF _LVOCloseLibrary ;close an open library (exec)
XREF _LVOInput ;get an input file handle (dos)
XREF _LVOOutput ;get an output file handle (dos)
XREF _LVORead ;input from an open file (dos)
XREF _LVOWrite ;print to an open file (dos)
XREF _LVOSPDiv ;divide d0 by d1 (math)
XREF _LVOSPMul ;multiply d0 by d1 (math)
XREF _LVOSPSub ;subtract d1 from d0 (math)
XREF _afp ;convert ASCII string to FFP
XREF _fpa ;go the other way
*
* Define macros for console I/O
*
WriteCon MACRO ;File Handle, Output String, String Length
move.l \1,d1 ;File Handle here
move.l \2,d2 ;String Address here
move.l \3,d3 ;Length of the String here
jsr _LVOWrite(a6) ;Assumes _DOSBase in a6!!
ENDM
ReadCon MACRO ;File Handle, Input Buffer, Buffer Length
move.l \1,d1 ;File Handle
move.l \2,d2 ;Buffer Address
move.l \3,d3 ;Buffer Length
jsr _LVORead(a6) ;_DOSBase had better be in a6!
ENDM
*
* Open the Dos library
*
Solve move.l _AbsExecBase,a6 ;OpenLib function in exec library
move.l #DOS_Name,a1 ;load pointer to the dos lib name
clr.l d0 ;will accept any version
jsr _LVOOpenLibrary(a6) ;open the library
move.l d0,_DOSBase ;base address returned in d0
beq NoDOS ;if no returned add., skip this
*
* Open the Math library
*
move.l #Mathffp_Name,a1 ;load pointer to the math lib name
clr.l d0
jsr _LVOOpenLibrary(a6)
move.l d0,_MathBase
beq NoMath ;again, if not there, can't run this
*
* Get the input file handle (The console is the default device)
*
move.l _DOSBase,a6 ;Input function in dos lib
jsr _LVOInput(a6) ;the console input is already open
;when the loader invokes a program
move.l d0,InHand ;save the handle from mischief
*
* Get the output file handle (Console also the default output device)
*
jsr _LVOOutput(a6) ;again, console is open upon loading
move.l d0,OutHand ;save this handle, too
*
* Prompt the user to enter the rank of matrix
*
WriteCon OutHand,#Msg1,#Msg1_Len
*
* Read in the rank of the matrix
*
ReadCon InHand,#RBuf,#RBuf_Len
clr.l d0 ;convert the input number to an int
move.b RBuf,d0 ;get first byte of buffer
andi.b #$0F,d0 ;strip off ASCII part
move.l d0,Rank ;save the result in memory
move.l d0,d4 ;and in d4 (to be a loop counter)
subq.l #1,d4 ;fix number of entries so DBRA works
move.l d4,Rank_1 ;and save it
lsl.l #2,d0 ;multiply the rank by 4: gives the
move.l d0,RowWidth ;number of bytes in each row, save it
*
* Prompt to enter coefficients
*
WriteCon OutHand,#Msg2,#Msg2_Len
*
* Read each coefficient
*
move.l #Matrix,a2 ;load pointer to matrix storage
move.l Rank_1,d4
RdCoef1 move.l Rank_1,d5 ;must read rank x rank number of coef
RdCoef2 move.l Rank,d0 ;recover rank value
move.l #PBuf,a3 ;recover print buffer start
sub.b d4,d0 ;calculate row value
ori.b #'0',d0 ;convert to character
move.b d0,(a3)+ ;put in print buffer
move.b #',',(a3)+ ;write a comma to separate indices
move.l Rank,d0 ;same idea
sub.b d5,d0 ;calculate column value
ori.b #'0',d0 ;convert to a character
move.b d0,(a3)+ ;put in the print buffer
move.b #':',(a3) ;make it look neat
WriteCon OutHand,#PBuf,#4 ;print the prompt
ReadCon InHand,#RBuf,#RBuf_Len ;read in the coefficient
move.l #RBuf,-(SP) ;push input string add. onto stack
jsr _afp ;call the C function to convert the
;string into an FFP
lea 4(SP),SP ;clean up the stack
move.l d0,(a2)+ ;save FFP into matrix
dbra d5,RdCoef2 ;get the next coefficient
dbra d4,RdCoef1 ;continue until the matrix is full
move.l a2,MatTop ;save the end of the matrix
*
* Read in the values in the solution vector
*
WriteCon OutHand,#Msg3,#Msg3_Len ;print prompt for sol. vec.
move.l #Solution,a2 ;load the pointer to the solution
;vector storage area
move.l Rank_1,d4 ;get this many values
RdSol move.l Rank,d0 ;recover rank value
sub.b d4,d0 ;calculate position
ori.b #'0',d0 ;make it a character
move.b d0,PBuf ;copy character to print buffer
move.b #':',PBuf+1 ;neaten the output
WriteCon OutHand,#PBuf,#2 ;print the value
ReadCon InHand,#RBuf,#RBuf_Len ;read the solution value
move.l #RBuf,-(SP) ;push string add. onto stack
jsr _afp ;call the C function
lea 4(SP),SP ;clean up the stack
move.l d0,(a2)+ ;save FFP in the storage area
dbra d4,RdSol ;continue until all sol's read
move.l a2,SolTop ;save pointer to solution vec. top
*
* Solve the simultaneous system
*
move.l _MathBase,a6 ;gonna do math for a while
move.l MatTop,a2 ;recover pointer to matrix end
move.l SolTop,a1 ;recover pointer to solution end
move.l Rank_1,d3 ;do for each row i
BigLoop move.l Rank,d0 ;the next few instructions caculate
sub.b d3,d0 ;the offset from the END of a row
lsl.l #2,d0 ;to the diagonal element
neg.l d0 ;=-(4*(rank - row_counter))
move.l d0,d2 ;save this factor for later
move.l 0(a2,d0),d1 ;get the diagonal element of row i
beq DivBy0 ;if it's zero, that's all we can do
move.l Rank_1,d4 ;do for each element of row i
move.l a2,a5 ;save the row end for later
Normal move.l -(a2),d0 ;get the next element
jsr _LVOSPDiv(a6) ;divide by the diag. (in d1)
move.l d0,(a2) ;store it back in the array
dbra d4,Normal ;continue until row i normalized
;Note: a2 left pointing to END of the
;row i-1
move.l -(a1),d0 ;get solution vector element
;corresponding to row i
jsr _LVOSPDiv(a6) ;divided by same diag element (d1)
move.l d0,(a1) ;save it back in the vector
move.l SolTop,a0 ;the operations below will leave
;the problem solution in the sol vec
move.l MatTop,a4 ;zero the elements in each row (j)
move.l Rank_1,d4 ;above and below the diag. of row i
ElimCol cmp.l d4,d3 ;skip this if j=i
beq NextRow
move.l a5,a3 ;recover the pointer to the end of
;row i
move.l 0(a4,d2),d6 ;get the diag. ele. of row j
move.l Rank_1,d5 ;do for each element of row j
FixRow move.l -(a3),d0 ;get the element of row i to be
move.l d6,d1 ;multiplied by the diag. ele. of j
jsr _LVOSPMul(a6) ;multiply them
move.l d0,d1 ;switch around the result
move.l -(a4),d0 ;get the affected element of row j
jsr _LVOSPSub(a6) ;subtract our product
move.l d0,(a4) ;save the result back in the matrix
dbra d5,FixRow ;continue for each element of row j
move.l d6,d1 ;also, do the same mult. and sub.
move.l (a1),d0 ;on the solution vector ele.
jsr _LVOSPMul(a6)
move.l d0,d1
move.l -(a0),d0
jsr _LVOSPSub(a6)
move.l d0,(a0)
bra ReLoop ;skip the rest
NextRow suba.l RowWidth,a4 ;if j=i then advance the row j
subq.l #4,a0 ;pointers to the next row, j-1
ReLoop dbra d4,ElimCol
dbra d3,BigLoop ;That's all for now
*
* All done so print the answers
*
move.l _DOSBase,a6 ;back to writing
WriteCon OutHand,#Msg5,#Msg5_Len ;print a line to this effect
move.l #Solution,a2 ;get the start of the sol. vec.
move.l Rank_1,d5 ;print the correct number of entries
SolLp2 move.l #PBuf,-(SP) ;push the buffer address
move.l d0,-(SP) ;WARNING: this does nothing, but is
;essential for the operation of _fpa
move.l (a2)+,-(SP) ;push the FFP to convert to a string
jsr _fpa ;call the routine to convert it
lea 12(SP),SP ;clean up the stack
move.w lf,PBuf+14 ;add a line feed to the buffer
WriteCon OutHand,#PBuf,#16 ;print it out
dbra d5,SolLp2 ;continue until all printed
bra CloseShop ;go to the end
DivBy0 move.l _DOSBase,a6 ;Uh Oh! Gotta stop
WriteCon OutHand,#Msg4,#Msg4_Len ;print the bad news
CloseShop move.l _AbsExecBase,a6 ;CloseLib in exec library
move.l _MathBase,a1 ;close the Math library
jsr _LVOCloseLibrary(a6) ;close it
NoMath move.l _AbsExecBase,a6
move.l _DOSBase,a1 ;close the dos library
jsr _LVOCloseLibrary(a6)
NoDOS clr.l d0 ;things went pretty well, bye.
rts
SECTION data,DATA
DOS_Name dc.b 'dos.library',0
Mathffp_Name:
dc.b 'mathffp.library',0
Msg1 dc.b 'Enter the rank of the coefficient matrix',13,10
Msg1_Len EQU *-Msg1
Msg2 dc.b 'Enter the coefficients as requested (row,col)',13,10
Msg2_Len EQU *-Msg2
Msg3 dc.b 'Enter the solution vector (row)',13,10
Msg3_Len EQU *-Msg3
Msg4 dc.b 'Oops. Division by zero!',13,10
Msg4_Len EQU *-Msg4
Msg5 dc.b 'The unknowns are:',13,10
Msg5_Len EQU *-Msg5
lf dc.w $0D0A
SECTION mem,BSS
* variables
_DOSBase ds.l 1
_MathBase ds.l 1
InHand ds.l 1
OutHand ds.l 1
Rank ds.l 1
Rank_1 ds.l 1
RowWidth ds.l 1
MatTop ds.l 1
SolTop ds.l 1
* buffers
RBuf ds.b 80
RBuf_Len EQU *-RBuf
PBuf ds.b 80
PBuf_Len EQU *-PBuf
Matrix ds.l 81
Solution ds.l 9
END